/*
  =====================================================
  开发需在vue环境下:
  1. 引入ali-oss 并配置
    let client = new OSS({
      region: 'oss-cn-shanghai',
      accessKeyId: 'LTAIHxBBBBBBBB',
      accessKeySecret: 'OQ4OGv5JVUvYuzp1kOnjzXBBBBBBBB',
      bucket: 'dbshs'
    })
    Vue.prototype.$client = client
  
  2. 引入date-fns
  3. 页面中需要插入两个元素，供图片压缩处理
    <img id="compressImg" style="display: none" />
    <canvas id="compressCvs" style="display: none" />
  =====================================================
*/
import OSS from 'ali-oss'
import { format } from 'date-fns'

const imgWidth = 1000 // 压缩后图片宽度
// const foldName = 'active/bagbind/' // ali-oss存储文件夹名称
const testMode = false

/*
  原图上传到阿里云oss
*/
const imgToOss = (vm, file, foldName) => {
  return new Promise(async (resolve, reject) => {

    let imgUrl = await putToOss(vm, file, foldName);

    resolve(imgUrl)
  })
}

/*
  base64上传阿里云oss
*/
const base64ImgToOss = (vm, base64Img, foldName) => {
  return new Promise(async (resolve, reject) => {

    // base64Img dom节点获取base64
    base64Img = nodeToString(base64Img)
      .replace("<", "<")
      .replace(">", ">")

    let imgBase64 = base64Img.substring(
      base64Img.indexOf('src="') + 5,
      base64Img.lastIndexOf('"')
    ) // 待优化
    
    let imgBuffer = await base64ToBuffer(imgBase64)

    let imgUrl = await putCanvasToOss(vm, foldName, imgBuffer)

    resolve(imgUrl)
  })
}

// dom 转 string
function nodeToString(node) {
  var tmpNode = document.createElement("div")
  tmpNode.appendChild(node.cloneNode(true))
  var str = tmpNode.innerHTML
  tmpNode = node = null // prevent memory leaks in IE
  return str
} 

/*
  canvas转base64上传阿里云oss
*/
const canvasToOss = (vm, cvs, foldName) => {
  return new Promise(async (resolve, reject) => {
    
    // 压缩后新图的base64
    let imgBase64 = cvs.toDataURL("image/png", 1.0)

    let imgBuffer = await base64ToBuffer(imgBase64)

    let imgUrl = await putCanvasToOss(vm, foldName, imgBuffer)

    resolve(imgUrl)
  })
}

/*
  压缩图片后上传到阿里云oss
*/
const imgToOssAfterCompress = (vm, file, foldName) => {
  return new Promise(async (resolve, reject) => {

    let imgBase64 = await imgCompressWithCanvas(file, imgWidth)

    let imgBuffer = await base64ToBuffer(imgBase64)

    let imgUrl = await putToOss(vm, file, foldName, imgBuffer)

    resolve(imgUrl)
  })
}

/*
  利用canvas绘图进行图片压缩
  返回压缩后图片base64
*/
const imgCompressWithCanvas = (file, imgWidth) => {
  return new Promise((resolve, reject) => {
    let img = document.getElementById("compressImg") // 页面中需要加入dom
    let cvs = document.getElementById("compressCvs") // 页面中需要加入dom
    
    // 上传的图片大于 1KB 时才压缩
    if (file && (file.size / 1024 > 1)) {
      let reader = new FileReader()
      reader.readAsDataURL(file) // 转成base64编码
      reader.onload = e => {
        let naturalBase64 = e.target.result // 原图base64编码
        img.src = naturalBase64
        img.onload = () => {
          let ratio = img.naturalWidth / img.naturalHeight // 原图宽高比
          cvs.width = imgWidth
          cvs.height = cvs.width / ratio
          let ctx = cvs.getContext('2d')
          ctx.drawImage(img, 0, 0, cvs.width, cvs.height)
          // 压缩后新图的base64
          let imgBase64 = cvs.toDataURL()

          resolve(imgBase64)
        }
      }
    }
  })
}

/*
  图片base64转buffer
  base64 -> blob -> arrayBuffer -> buffer
*/
const base64ToBuffer = (base64) => {
  return new Promise((resolve, reject) => {
    // base64转blob
    const blob = toBlob(base64)
    // blob转arrayBuffer
    const reader = new FileReader()
    reader.readAsArrayBuffer(blob)
    reader.onload = async event => {
      let result = event.target.result
      // arrayBuffer转Buffer
      const buffer = new OSS.Buffer(result)
      resolve(buffer)
    }
  })
}

/*
  base64转blob
 */
const toBlob = (imgBase64) => {
  const base64 = imgBase64.split(',').pop()
  const fileType = imgBase64.split(';').shift().split(':').pop()
  let bytes = window.atob(base64)
  let n = bytes.length
  let u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bytes.charCodeAt(n)
  }
  return new Blob([u8arr], { type: fileType })
}

/*
  上传图片至alioss
  返回成功到图片网络地址
*/
const putToOss = (vm, fileOrigin, foldName, buffer) => {
  return new Promise(async (resolve, reject) => {
    let timestamp = format(new Date(), "yyyy-MM-dd-HHmmss")
    let randomNum = parseInt(Math.random() * 99);
    let picName = testMode ? "test-" : "";
    picName += timestamp + "-" + randomNum;
    let fileType = fileOrigin.type.split("/")[1];
    let upData = buffer ? buffer : fileOrigin;

    try {
      let result = await vm.$client.put(
        foldName + picName + "." + fileType,
        upData
      );
      let picUrl = result.url;
      resolve(picUrl);
    } catch (e) {
      console.log("Error with alioss: ", e);
      reject(e);
    }
  });
};

/*
  上传canvas图片至alioss
  返回成功到图片网络地址
*/
const putCanvasToOss = (vm, foldName, buffer) => {
  return new Promise(async (resolve, reject) => {
    let timestamp = format(new Date(), "yyyy-MM-dd-HHmmss")
    let randomNum = parseInt(Math.random() * 99)
    let picName = testMode ? "test-" : ""
    picName += timestamp + "-" + randomNum
    let fileType = 'png'
    let upData = buffer

    try {
      let result = await vm.$client.put(
        foldName + picName + "." + fileType,
        upData
      )
      let picUrl = result.url
      resolve(picUrl)
    } catch (e) {
      console.log("Error with alioss: ", e)
      reject(e)
    }
  })
}

export { imgToOss, canvasToOss, base64ImgToOss, imgToOssAfterCompress }